package com.clx.loadbalancer;

import com.clx.CrpcBootstrap;
import com.clx.discovery.Registry;
import com.clx.exceptions.LoadBalancerException;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public abstract class AbstractLoadBalancer implements LoadBalancer {
    // 服务名 -> 选择器的缓存
    private Map<String, Selector> cache = new ConcurrentHashMap<>(8);

    @Override
    public InetSocketAddress selectServiceAddress(String serviceName) {
        // 1、优先从cache中获取一个选择器
        Selector selector = cache.get(serviceName);

        // 2、如果没有，就需要为这个service创建一个selector
        if (selector == null) {
            // 对于这个负载均衡器，内部应该维护服务列表作为缓存
            List<InetSocketAddress> serviceList = CrpcBootstrap.getInstance().getRegistry().lookup(serviceName);

            // 提供一些算法负责选取合适的节点
            selector = getSelector(serviceList);
            cache.put(serviceName,selector);
        }
        // 获取可用节点
        return selector.getNext();
    }

    @Override
    public synchronized void reLoadBalance(String serviceName,List<InetSocketAddress> addresses) {
        // 我们可以根据新的服务列表生成新的selector
        cache.put(serviceName,getSelector(addresses));
    }

    /**
     * 由子类实现「选择器创建逻辑」（模板方法模式）
     */

    protected abstract Selector getSelector(List<InetSocketAddress> serviceList);
}


